<!--
xiaozhi-status 状态监控节点
用于监控MCP连接状态、工具状态和系统健康状况
-->

<script type="text/javascript">
  RED.nodes.registerType('xiaozhi-status', {
    category: '小智MCP',
    color: '#FFE4B5',
    defaults: {
      name: { value: '' },
      xiaozhi: { value: '', type: 'xiaozhi-config', required: true },
      monitorMode: { value: 'auto' },
      outputMode: { value: 'full' },
      pollingInterval: { value: 10000, validate: RED.validators.number() },
      includeStats: { value: true },
      includeHealth: { value: true },
      includeTools: { value: true },
      autoStart: { value: true }
    },
    inputs: 1,
    outputs: 1,
    inputLabels: '控制命令',
    outputLabels: '状态信息',
    icon: 'font-awesome/fa-heartbeat',
    label: function() {
      return this.name || '状态监控';
    },
    labelStyle: function() {
      return this.name ? 'node_label_italic' : '';
    },
    paletteLabel: '状态监控',
    oneditprepare: function() {
      var node = this;
      
      // 监控模式变化处理
      $('#node-input-monitorMode').on('change', function() {
        var mode = $(this).val();
        var intervalContainer = $('#polling-interval-container');
        var modeHelp = $('#monitor-mode-help');
        
        var helpTexts = {
          'auto': '自动监控：启动时开始监控，定期检查状态变化',
          'manual': '手动监控：仅响应输入消息触发状态检查',
          'scheduled': '定时监控：按指定间隔定期输出状态信息'
        };
        
        modeHelp.text(helpTexts[mode] || '');
        
        if (mode === 'auto' || mode === 'scheduled') {
          intervalContainer.show();
        } else {
          intervalContainer.hide();
        }
      });

      // 输出模式变化处理
      $('#node-input-outputMode').on('change', function() {
        var mode = $(this).val();
        var helpTexts = {
          'full': '输出完整的状态信息，包括所有配置的监控项',
          'changes': '仅在状态发生变化时输出，包含变化详情',
          'summary': '输出简化的状态摘要信息'
        };
        $('#output-mode-help').text(helpTexts[mode] || '');
      });

      // 轮询间隔单位转换
      $('#polling-unit').on('change', function() {
        var unit = $(this).val();
        var intervalField = $('#node-input-pollingInterval');
        var currentValue = parseInt(intervalField.val()) || 10000;
        
        switch(unit) {
          case 'seconds':
            intervalField.val(Math.round(currentValue / 1000));
            break;
          case 'minutes':
            intervalField.val(Math.round(currentValue / 60000));
            break;
          default: // milliseconds
            // 保持原值
            break;
        }
      });

      // 实时状态查看
      var statusDisplay = $('#status-display');
      var refreshStatusBtn = $('#refresh-status');
      var monitoringStats = $('#monitoring-stats');

      var updateStatusDisplay = function() {
        if (!node.id) {
          statusDisplay.html('<p class="status-item">请先保存节点配置</p>');
          return;
        }

        refreshStatusBtn.prop('disabled', true).text('获取中...');

        $.ajax({
          url: 'xiaozhi-status/' + node.id + '/status',
          method: 'GET',
          success: function(data) {
            var html = '<div class="status-container">';
            
            // MCP连接状态
            html += '<div class="status-section">';
            html += '<h4><i class="fa fa-plug"></i> MCP连接</h4>';
            html += '<div class="status-item">状态: <span class="status-value ' + 
                   (data.mcp.connected ? 'connected' : 'disconnected') + '">' +
                   (data.mcp.connected ? '已连接' : '未连接') + '</span></div>';
            html += '<div class="status-item">端点: <span class="status-value">' + 
                   (data.mcp.endpoint || '未配置') + '</span></div>';
            if (data.mcp.lastError) {
              html += '<div class="status-item">错误: <span class="status-value error">' + 
                     data.mcp.lastError + '</span></div>';
            }
            html += '</div>';

            // 工具信息
            if (data.tools) {
              html += '<div class="status-section">';
              html += '<h4><i class="fa fa-cogs"></i> 注册工具</h4>';
              html += '<div class="status-item">数量: <span class="status-value">' + 
                     data.tools.count + '</span></div>';
              if (data.tools.names && data.tools.names.length > 0) {
                html += '<div class="status-item">工具列表:</div>';
                html += '<ul class="tool-list">';
                data.tools.names.forEach(function(name) {
                  html += '<li>' + name + '</li>';
                });
                html += '</ul>';
              }
              html += '</div>';
            }

            // 健康状态
            if (data.mcp.health) {
              html += '<div class="status-section">';
              html += '<h4><i class="fa fa-heartbeat"></i> 健康状态</h4>';
              html += '<div class="status-item">状态: <span class="status-value ' + 
                     data.mcp.health.status + '">' + data.mcp.health.status + '</span></div>';
              if (data.mcp.health.reason) {
                html += '<div class="status-item">原因: <span class="status-value">' + 
                       data.mcp.health.reason + '</span></div>';
              }
              html += '</div>';
            }

            html += '</div>';
            statusDisplay.html(html);
          },
          error: function() {
            statusDisplay.html('<p class="status-item error">无法获取状态信息</p>');
          },
          complete: function() {
            refreshStatusBtn.prop('disabled', false).text('刷新状态');
          }
        });
      };

      var updateMonitoringStats = function() {
        if (!node.id) return;

        $.ajax({
          url: 'xiaozhi-status/' + node.id + '/stats',
          method: 'GET',
          success: function(data) {
            var html = '<div class="stats-container">';
            html += '<div class="stats-item">监控状态: <span class="' + 
                   (data.monitoring ? 'monitoring' : 'stopped') + '">' +
                   (data.monitoring ? '监控中' : '已停止') + '</span></div>';
            html += '<div class="stats-item">轮询间隔: ' + data.pollingInterval + 'ms</div>';
            html += '<div class="stats-item">总输出: ' + data.totalOutputs + '次</div>';
            html += '<div class="stats-item">状态变化: ' + data.statusChanges + '次</div>';
            html += '<div class="stats-item">连接变化: ' + data.connectionChanges + '次</div>';
            if (data.startedAt) {
              html += '<div class="stats-item">运行时间: ' + 
                     Math.round(data.uptime / 1000) + '秒</div>';
            }
            html += '</div>';
            monitoringStats.html(html);
          },
          error: function() {
            monitoringStats.html('<p class="error">无法获取统计信息</p>');
          }
        });
      };

      // 刷新按钮事件
      refreshStatusBtn.on('click', function() {
        updateStatusDisplay();
        updateMonitoringStats();
      });

      // 监控控制按钮
      $('#start-monitoring').on('click', function() {
        if (!node.id) {
          RED.notify('请先保存节点配置', 'warn');
          return;
        }

        var button = $(this);
        button.prop('disabled', true);

        $.ajax({
          url: 'xiaozhi-status/' + node.id + '/control',
          method: 'POST',
          contentType: 'application/json',
          data: JSON.stringify({ action: 'start' }),
          success: function(data) {
            RED.notify('监控已启动', 'success');
            updateMonitoringStats();
          },
          error: function() {
            RED.notify('启动监控失败', 'error');
          },
          complete: function() {
            button.prop('disabled', false);
          }
        });
      });

      $('#stop-monitoring').on('click', function() {
        if (!node.id) {
          RED.notify('请先保存节点配置', 'warn');
          return;
        }

        var button = $(this);
        button.prop('disabled', true);

        $.ajax({
          url: 'xiaozhi-status/' + node.id + '/control',
          method: 'POST',
          contentType: 'application/json',
          data: JSON.stringify({ action: 'stop' }),
          success: function(data) {
            RED.notify('监控已停止', 'success');
            updateMonitoringStats();
          },
          error: function() {
            RED.notify('停止监控失败', 'error');
          },
          complete: function() {
            button.prop('disabled', false);
          }
        });
      });

      // 查看历史按钮
      $('#view-history').on('click', function() {
        if (!node.id) {
          RED.notify('请先保存节点配置', 'warn');
          return;
        }

        $.ajax({
          url: 'xiaozhi-status/' + node.id + '/history?limit=10',
          method: 'GET',
          success: function(data) {
            var historyText = '最近10条状态历史:\n\n';
            data.forEach(function(item, index) {
              historyText += (index + 1) + '. ' + new Date(item.timestamp).toLocaleString();
              if (item.changes && item.changes.length > 0) {
                historyText += ' - 变化: ' + item.changes.join(', ');
              }
              historyText += '\n';
            });
            RED.notify(historyText, 'success');
          },
          error: function() {
            RED.notify('获取历史记录失败', 'error');
          }
        });
      });

      // 帮助信息切换
      $('.help-toggle').on('click', function() {
        var target = $(this).data('target');
        $(target).toggle();
      });

      // 初始化
      setTimeout(function() {
        $('#node-input-monitorMode').trigger('change');
        $('#node-input-outputMode').trigger('change');
        updateStatusDisplay();
        updateMonitoringStats();
      }, 100);
    },
    oneditsave: function() {
      // 转换轮询间隔单位
      var unit = $('#polling-unit').val();
      var interval = parseInt($('#node-input-pollingInterval').val()) || 10;
      
      switch(unit) {
        case 'seconds':
          this.pollingInterval = interval * 1000;
          break;
        case 'minutes':
          this.pollingInterval = interval * 60000;
          break;
        default: // milliseconds
          this.pollingInterval = interval;
          break;
      }
    }
  });
</script>

<script type="text/html" data-template-name="xiaozhi-status">
  <div class="form-row">
    <label for="node-input-name"><i class="fa fa-tag"></i> 节点名称</label>
    <input type="text" id="node-input-name" placeholder="可选的节点名称">
  </div>

  <div class="form-row">
    <label for="node-input-xiaozhi"><i class="fa fa-plug"></i> 小智配置</label>
    <input type="text" id="node-input-xiaozhi">
  </div>

  <hr>

  <div class="form-row">
    <label for="node-input-monitorMode"><i class="fa fa-eye"></i> 监控模式</label>
    <select id="node-input-monitorMode">
      <option value="auto">自动监控</option>
      <option value="manual">手动监控</option>
      <option value="scheduled">定时监控</option>
    </select>
    <div class="red-ui-help">
      <p id="monitor-mode-help">自动监控：启动时开始监控，定期检查状态变化</p>
    </div>
  </div>

  <div id="polling-interval-container" class="form-row">
    <label for="node-input-pollingInterval"><i class="fa fa-clock-o"></i> 轮询间隔</label>
    <input type="number" id="node-input-pollingInterval" style="width: 60px;" min="1" step="1" value="10">
    <select id="polling-unit" style="width: 80px; margin-left: 5px;">
      <option value="milliseconds">毫秒</option>
      <option value="seconds" selected>秒</option>
      <option value="minutes">分钟</option>
    </select>
  </div>

  <div class="form-row">
    <label for="node-input-outputMode"><i class="fa fa-share"></i> 输出模式</label>
    <select id="node-input-outputMode">
      <option value="full">完整信息</option>
      <option value="changes">仅变化</option>
      <option value="summary">简要摘要</option>
    </select>
    <div class="red-ui-help">
      <p id="output-mode-help">输出完整的状态信息，包括所有配置的监控项</p>
    </div>
  </div>

  <hr>

  <div class="form-row">
    <label>监控项目</label>
    <div style="margin-left: 105px;">
      <label style="width: auto;">
        <input type="checkbox" id="node-input-includeStats" style="width: auto; margin-right: 5px;">
        包含统计信息
      </label><br>
      <label style="width: auto;">
        <input type="checkbox" id="node-input-includeHealth" style="width: auto; margin-right: 5px;">
        包含健康状态
      </label><br>
      <label style="width: auto;">
        <input type="checkbox" id="node-input-includeTools" style="width: auto; margin-right: 5px;">
        包含工具信息
      </label>
    </div>
  </div>

  <div class="form-row">
    <label>&nbsp;</label>
    <input type="checkbox" id="node-input-autoStart" style="display:inline-block; width:auto; vertical-align:top;">
    <label for="node-input-autoStart" style="width:70%;">启动时自动开始监控</label>
  </div>

  <hr>

  <div class="form-row">
    <label>实时状态</label>
    <button type="button" id="refresh-status" class="red-ui-button" style="margin-left: 10px;">
      <i class="fa fa-refresh"></i> 刷新状态
    </button>
    <button type="button" class="help-toggle red-ui-button" data-target="#commands-help" style="margin-left: 5px;">
      <i class="fa fa-question-circle"></i> 控制命令
    </button>
  </div>

  <div id="status-display" class="status-display">
    <p class="status-item">点击刷新状态按钮获取实时信息</p>
  </div>

  <div id="commands-help" class="red-ui-help" style="display:none;">
    <h4>输入控制命令</h4>
    <p>发送以下字符串到输入端口控制监控行为：</p>
    <ul>
      <li><code>"start"</code> - 开始监控</li>
      <li><code>"stop"</code> - 停止监控</li>
      <li><code>"check"</code> 或 <code>"status"</code> - 立即检查状态</li>
      <li><code>"stats"</code> - 输出监控统计信息</li>
      <li><code>"history"</code> - 输出状态历史记录</li>
    </ul>
    <p>也可以发送对象命令：</p>
    <pre>
{
  "action": "configure",
  "pollingInterval": 5000,
  "outputMode": "changes"
}
    </pre>
  </div>

  <div class="form-row">
    <label>监控控制</label>
    <button type="button" id="start-monitoring" class="red-ui-button">
      <i class="fa fa-play"></i> 启动监控
    </button>
    <button type="button" id="stop-monitoring" class="red-ui-button" style="margin-left: 5px;">
      <i class="fa fa-stop"></i> 停止监控
    </button>
    <button type="button" id="view-history" class="red-ui-button" style="margin-left: 10px;">
      <i class="fa fa-history"></i> 查看历史
    </button>
  </div>

  <div id="monitoring-stats" class="status-display">
    <p class="status-item">监控统计信息将在此显示</p>
  </div>
</script>

<script type="text/html" data-help-name="xiaozhi-status">
  <p>xiaozhi-status节点用于监控小智MCP连接状态、工具状态和系统健康状况，提供实时的状态信息。</p>

  <h3>配置说明</h3>
  <dl class="message-properties">
    <dt>小智配置 <span class="property-type">xiaozhi-config</span></dt>
    <dd>选择要监控的小智MCP连接节点</dd>

    <dt>监控模式 <span class="property-type">string</span></dt>
    <dd>监控行为模式：自动监控、手动监控或定时监控</dd>

    <dt>轮询间隔 <span class="property-type">number</span></dt>
    <dd>在自动或定时模式下的状态检查间隔</dd>

    <dt>输出模式 <span class="property-type">string</span></dt>
    <dd>状态信息的输出格式：完整信息、仅变化或简要摘要</dd>

    <dt>监控项目 <span class="property-type">boolean</span></dt>
    <dd>选择要包含在状态信息中的项目</dd>
  </dl>

  <h3>输入消息</h3>
  <p>接收控制命令：</p>
  <dl class="message-properties">
    <dt>payload <span class="property-type">string | object</span></dt>
    <dd>控制命令字符串或配置对象</dd>
  </dl>

  <h4>支持的命令</h4>
  <ul>
    <li><code>"start"</code> - 开始监控</li>
    <li><code>"stop"</code> - 停止监控</li>
    <li><code>"check"</code> - 立即检查状态</li>
    <li><code>"stats"</code> - 输出统计信息</li>
    <li><code>"history"</code> - 输出历史记录</li>
  </ul>

  <h3>输出消息</h3>
  <h4>完整信息模式</h4>
  <dl class="message-properties">
    <dt>payload.timestamp <span class="property-type">string</span></dt>
    <dd>状态检查的时间戳</dd>

    <dt>payload.mcp <span class="property-type">object</span></dt>
    <dd>MCP连接状态信息</dd>

    <dt>payload.tools <span class="property-type">object</span></dt>
    <dd>注册工具的信息</dd>

    <dt>payload.system <span class="property-type">object</span></dt>
    <dd>系统和监控信息</dd>

    <dt>_statusUpdate <span class="property-type">object</span></dt>
    <dd>状态更新的元信息</dd>
  </dl>

  <h4>仅变化模式</h4>
  <p>仅在状态发生变化时输出，包含额外字段：</p>
  <dl class="message-properties">
    <dt>payload.changes <span class="property-type">array</span></dt>
    <dd>发生的变化列表</dd>

    <dt>payload.previousStatus <span class="property-type">object</span></dt>
    <dd>前一次的状态信息</dd>
  </dl>

  <h3>MCP状态信息</h3>
  <dl class="message-properties">
    <dt>mcp.connected <span class="property-type">boolean</span></dt>
    <dd>MCP服务器连接状态</dd>

    <dt>mcp.connectionState <span class="property-type">string</span></dt>
    <dd>详细的连接状态</dd>

    <dt>mcp.endpoint <span class="property-type">string</span></dt>
    <dd>MCP服务器端点地址</dd>

    <dt>mcp.health <span class="property-type">object</span></dt>
    <dd>连接健康状态</dd>

    <dt>mcp.stats <span class="property-type">object</span></dt>
    <dd>连接统计信息</dd>
  </dl>

  <h3>工具状态信息</h3>
  <dl class="message-properties">
    <dt>tools.count <span class="property-type">number</span></dt>
    <dd>已注册工具的数量</dd>

    <dt>tools.names <span class="property-type">array</span></dt>
    <dd>工具名称列表</dd>

    <dt>tools.details <span class="property-type">array</span></dt>
    <dd>工具详细信息（包含统计时）</dd>
  </dl>

  <h3>使用示例</h3>
  <p><strong>基础监控设置</strong></p>
  <ol>
    <li>选择小智配置节点</li>
    <li>设置监控模式为"自动监控"</li>
    <li>设置轮询间隔为10秒</li>
    <li>选择输出模式为"仅变化"</li>
    <li>启用所有监控项目</li>
  </ol>

  <p><strong>手动控制监控</strong></p>
  <ol>
    <li>设置监控模式为"手动监控"</li>
    <li>连接inject节点，发送"start"命令开始监控</li>
    <li>发送"check"命令手动检查状态</li>
    <li>发送"stop"命令停止监控</li>
  </ol>

  <h3>状态变化事件</h3>
  <p>节点会检测并报告以下状态变化：</p>
  <ul>
    <li>MCP连接状态变化（连接/断开）</li>
    <li>工具数量变化（注册/注销）</li>
    <li>健康状态变化</li>
    <li>连接端点变化</li>
  </ul>

  <h3>注意事项</h3>
  <ul>
    <li>监控频率不宜过高，避免影响系统性能</li>
    <li>仅变化模式可以减少不必要的输出</li>
    <li>包含统计信息会增加输出数据量</li>
    <li>手动模式下需要主动发送命令才会检查状态</li>
    <li>状态历史有最大条目限制，超出会自动清理</li>
  </ul>
</script>

<style>
  .red-ui-help {
    font-size: 12px;
    color: #666;
    margin-top: 5px;
  }
  
  .red-ui-help h4 {
    margin: 10px 0 5px 0;
    font-size: 13px;
    font-weight: bold;
  }
  
  .red-ui-help pre {
    background: #f5f5f5;
    padding: 8px;
    margin: 5px 0;
    font-size: 11px;
    border-radius: 3px;
    overflow-x: auto;
  }
  
  .red-ui-help ul {
    margin: 5px 0;
    padding-left: 20px;
  }

  .status-display {
    border: 1px solid #ddd;
    padding: 10px;
    margin: 10px 0;
    background: #f9f9f9;
    border-radius: 4px;
    min-height: 60px;
    max-height: 300px;
    overflow-y: auto;
    font-size: 12px;
  }

  .status-container {
    margin: 0;
  }

  .status-section {
    margin-bottom: 15px;
    border-bottom: 1px solid #eee;
    padding-bottom: 10px;
  }

  .status-section:last-child {
    border-bottom: none;
  }

  .status-section h4 {
    margin: 0 0 8px 0;
    font-size: 13px;
    color: #333;
  }

  .status-item {
    margin: 3px 0;
    font-size: 12px;
  }

  .status-value {
    font-weight: bold;
  }

  .status-value.connected {
    color: #5cb85c;
  }

  .status-value.disconnected {
    color: #d9534f;
  }

  .status-value.error {
    color: #d9534f;
  }

  .status-value.healthy {
    color: #5cb85c;
  }

  .tool-list {
    margin: 5px 0 5px 20px;
    padding: 0;
  }

  .tool-list li {
    font-size: 11px;
    color: #666;
  }

  .stats-container {
    margin: 0;
  }

  .stats-item {
    margin: 3px 0;
    font-size: 12px;
  }

  .stats-item .monitoring {
    color: #5cb85c;
    font-weight: bold;
  }

  .stats-item .stopped {
    color: #d9534f;
    font-weight: bold;
  }
</style>